package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"time"
)

func onevone() {

	ch := make(chan int)
	go func() {
		ch <- 1
		close(ch)
	}()

	go func() {
		i := <-ch
		fmt.Println(i)
	}()
}

func onevm() {
	ch := make(chan int)
	go func() {
		ch <- 1
		close(ch)
	}()

	for i := 0; i < 100; i++ {
		go func(i int) {
			num := <-ch
			fmt.Println(i, "接收num = ", num)
		}(i)
	}
}

func nvone() {
	rand.Seed(time.Now().UnixNano())
	const Max = 10000
	const NumSenders = 1000

	dataCh := make(chan int, 100)
	stopCh := make(chan struct{})

	for i := 0; i < NumSenders; i++ {
		go func() {
			select {
			case <-stopCh:
				return
			case dataCh <- rand.Intn(Max):
			}
		}()
	}

	go func() {
		for value := range dataCh {
			if value == Max-1 {
				fmt.Println("send stop signal to senders")
				close(stopCh)
				return
			}
			fmt.Println(value)
		}
	}()
}

func nvm() {

	const Max = 10000
	const NumSenders = 1000
	const NumReaders = 1000

	dataCh := make(chan int, 100)
	stopCh := make(chan struct{})
	toStopCh := make(chan string, 1)

	go func() {
		<-toStopCh
		close(stopCh)
	}()

	for i := 0; i < NumSenders; i++ {
		go func(id string) {
			for {
				value := rand.Intn(Max)
				if value == 0 {
					select {
					case toStopCh <- "sender#" + id:
					default:
					}
				}

				select {
				case <-stopCh:
					return
				case dataCh <- value:
				}
			}
		}(strconv.Itoa(i))
	}

	for i := 0; i < NumReaders; i++ {

		go func(id string) {

			for {
				select {
				case <-stopCh:
					return
				case value := <-dataCh:
					if value == Max-1 {
						select {
						case toStopCh <- "reader#" + id:
						default:
						}
						return
					}
					fmt.Println(value)
				}
			}
		}(strconv.Itoa(i))
	}

	select {
	case <-time.After(time.Hour):

	}
}

func main() {

	onevm()

	time.Sleep(time.Minute)
}
